/*
 * Copyright 2011 Angel Sanadinov
 *
 * This file is part of VBox WMI.
 *
 * VBox WMI is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * VBox WMI is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with VBox WMI.  If not, see <http://www.gnu.org/licenses/>.
 */

package Beans.Requests.MachineManagement;

import Beans.Requests.MachineManagement.Components.*;
import Utilities.Functions;
import Utilities.PermissionsConstants;
import java.util.ArrayList;

/**
 * Instances of this class are used by the user interface when a request to
 * create a new virtual machine is sent to the machines management service.
 *
 * @author Angel Sanadinov
 */
public class CreateMachineRequest extends MachineManagementRequest
{
    private String machineName;         //the name of the new machine
    private String osTypeId;            //the OS type id
    private String machineDescription;  //the machine description
    private String permissions;         //the machine's permissions
    private AudioSettings audioSettings;//Audio settings
    private BIOSSettings biosSettings;  //BIOS settings
    private BootSettings bootSettings;  //Boot settings
    private CPUSettings cpuSettings;    //CPU settings
    private IOSettings ioSettings;      //I/O settings
    private MemorySettings memorySettings; //Memory Settings
    private NetworkAdapterSettings[] networksSettings; //Networking settings
    private ArrayList<SharedFolderSettings> sharedFoldersSettings; //Shared Folder settings
    private StorageSettings storageSettings; //Storage settings
    private VRDPSettings vrdpSettings;  //VRDP server settings
    private VideoSettings videoSettings;//Video settings

    /**
     * No-argument constructor. <br><br>
     * All fields are set to their invalid values.
     */
    public CreateMachineRequest()
    {
        super();
        this.machineName = null;
        this.osTypeId = null;
        this.machineDescription = null;
        this.audioSettings = null;
        this.biosSettings = null;
        this.bootSettings = null;
        this.cpuSettings = null;
        this.ioSettings = null;
        this.memorySettings = null;
        this.networksSettings = null;
        this.sharedFoldersSettings = null;
        this.storageSettings = null;
        this.vrdpSettings = null;
        this.videoSettings = null;
        setRequestedAction(PermissionsConstants.ACTION_MACHINE_CREATE);
    }

    /**
     * Constructs an incomplete request for creating a new virtual machine. <br><br>
     *
     * <b>Note:</b> <i>All machine data needs to be explicitly set!</i>
     *
     * @param requestorId the id of the user that made the request
     * @param serverId the id of the server on which the machine will reside
     * @param permissions permissions for the new machine
     */
    public CreateMachineRequest(int requestorId, int serverId, String permissions)
    {
        this();
        setRequestorId(requestorId);
        setServerId(serverId);
        this.permissions = permissions;
        setRequestedAction(PermissionsConstants.ACTION_MACHINE_CREATE);
    }

    /**
     * Constructs a complete request for creating a new virtual machine. <br><br>
     *
     * <b>Note:</b> <i>No additional request setup is needed.</i>
     *
     * @param requestorId the id of the user that made the request
     * @param serverId the id of the server on which the machine will reside
     * @param permissions permissions for the new machine
     * @param machineName the name of the machine
     * @param osTypeId the operating system type id of the machine
     * @param machineDescription the machine description
     * @param audioSettings audio settings
     * @param biosSettings BIOS settings for the new machine
     * @param bootSettings Boot settings for the new machine
     * @param cpuSettings CPU settings for the new machine
     * @param ioSettings I/O settings for the new machine
     * @param memorySettings Memory settings for the new machine
     * @param networksSettings Networking settings for the new machine (for each network adapter)
     * @param sharedFoldersSettings Shared folders settings for the new machine
     * @param storageSettings Storage settings for the new machine
     * @param vrdpSettings VRDP server settings for the new machine
     * @param videoSettings Video settings for the new machine
     */
    public CreateMachineRequest(int requestorId, int serverId, String permissions,
                                String machineName, String osTypeId, String machineDescription,
                                AudioSettings audioSettings, BIOSSettings biosSettings,
                                BootSettings bootSettings, CPUSettings cpuSettings, 
                                IOSettings ioSettings, MemorySettings memorySettings,
                                NetworkAdapterSettings[] networksSettings,
                                ArrayList<SharedFolderSettings> sharedFoldersSettings,
                                StorageSettings storageSettings,VRDPSettings vrdpSettings,
                                VideoSettings videoSettings)
    {
        this(requestorId, serverId, permissions);
        this.machineName = machineName;
        this.osTypeId = osTypeId;
        this.machineDescription = machineDescription;
        this.audioSettings = audioSettings;
        this.biosSettings = biosSettings;
        this.bootSettings = bootSettings;
        this.cpuSettings = cpuSettings;
        this.ioSettings = ioSettings;
        this.memorySettings = memorySettings;
        this.networksSettings = networksSettings;
        this.sharedFoldersSettings = sharedFoldersSettings;
        this.storageSettings = storageSettings;
        this.vrdpSettings = vrdpSettings;
        this.videoSettings = videoSettings;
    }

    /**
     * Retrieves the new machine's name.
     *
     * @return the machine name
     */
    public String getMachineName()
    {
        return machineName;
    }

    /**
     * Retrieves the operating system type id of the machine.
     *
     * @return the OS type id
     */
    public String getOsTypeId()
    {
        return osTypeId;
    }

    /**
     * Retrieves the description of the new machine.
     *
     * @return the machine description
     */
    public String getMachineDescription()
    {
        return machineDescription;
    }

    /**
     * Retrieves the permissions of the machine.
     *
     * @return the machine's permissions
     */
    public String getPermissions()
    {
        return permissions;
    }

    /**
     * Retrieves the audio settings of the new machine.
     *
     * @return the audio settings, if available or <code>null</code> otherwise
     */
    public AudioSettings getAudioSettings()
    {
        return audioSettings;
    }

    /**
     * Retrieves the BIOS settings of the new machine.
     *
     * @return the BIOS settings, if available or <code>null</code> otherwise
     */
    public BIOSSettings getBiosSettings()
    {
        return biosSettings;
    }

    /**
     * Retrieves the boot settings of the new machine.
     *
     * @return the boot settings, if available or <code>null</code> otherwise
     */
    public BootSettings getBootSettings()
    {
        return bootSettings;
    }

    /**
     * Retrieves the CPU settings of the new machine.
     *
     * @return the CPU settings, if available or <code>null</code> otherwise
     */
    public CPUSettings getCpuSettings()
    {
        return cpuSettings;
    }

    /**
     * Retrieves the I/O settings of the new machine.
     *
     * @return the I/O settings, if available or <code>null</code> otherwise
     */
    public IOSettings getIoSettings()
    {
        return ioSettings;
    }

    /**
     * Retrieves the memory settings of the new machine.
     *
     * @return the memory settings, if available or <code>null</code> otherwise
     */
    public MemorySettings getMemorySettings()
    {
        return memorySettings;
    }

    /**
     * Retrieves the networking settings of the new machine (for each network adapter).
     *
     * @return the networking settings, if available or <code>null</code> otherwise
     */
    public NetworkAdapterSettings[] getNetworksSettings()
    {
        return networksSettings;
    }

    /**
     * Retrieves the shared folders settings of the new machine.
     *
     * @return the shared folders settings, if available or <code>null</code> otherwise
     */
    public ArrayList<SharedFolderSettings> getSharedFoldersSettings()
    {
        return sharedFoldersSettings;
    }

    /**
     * Retrieves the storage settings of the new machine.
     *
     * @return the storage settings, if available or <code>null</code> otherwise
     */
    public StorageSettings getStorageSettings()
    {
        return storageSettings;
    }

    /**
     * Retrieves the VRDP settings of the new machine.
     *
     * @return the VRDP settings, if available or <code>null</code> otherwise
     */
    public VRDPSettings getVrdpSettings()
    {
        return vrdpSettings;
    }

    /**
     * Retrieves the video settings of the new machine.
     *
     * @return the video settings, if available or <code>null</code> otherwise
     */
    public VideoSettings getVideoSettings()
    {
        return videoSettings;
    }

    /**
     * Sets the name of the new virtual machine.
     *
     * @param machineName the machine name
     */
    public void setMachineName(String machineName)
    {
        this.machineName = machineName;
    }

    /**
     * Sets the operating system type id of the new machine.
     *
     * @param osTypeId the OS type id
     */
    public void setOsTypeId(String osTypeId)
    {
        this.osTypeId = osTypeId;
    }

    /**
     * Sets the description of the new machine.
     *
     * @param machineDescription the machine description
     */
    public void setMachineDescription(String machineDescription)
    {
        this.machineDescription = machineDescription;
    }

    /**
     * Sets the permissions of the new machine.
     *
     * @param permissions the machine's permissions
     */
    public void setPermissions(String permissions)
    {
        this.permissions = permissions;
    }

    /**
     * Sets the audio settings for the new machine.
     *
     * @param audioSettings the audio settings
     */
    public void setAudioSettings(AudioSettings audioSettings)
    {
        this.audioSettings = audioSettings;
    }

    /**
     * Sets the BIOS settings for the new machine.
     *
     * @param biosSettings the BIOS settings
     */
    public void setBiosSettings(BIOSSettings biosSettings)
    {
        this.biosSettings = biosSettings;
    }

    /**
     * Sets the boot settings for the new machine.
     *
     * @param bootSettings the boot settings
     */
    public void setBootSettings(BootSettings bootSettings)
    {
        this.bootSettings = bootSettings;
    }

    /**
     * Sets the CPU settings for the new machine.
     *
     * @param cpuSettings the CPU settings
     */
    public void setCpuSettings(CPUSettings cpuSettings)
    {
        this.cpuSettings = cpuSettings;
    }

    /**
     * Sets the I/O settings for the new machine.
     *
     * @param ioSettings the I/O settings
     */
    public void setIoSettings(IOSettings ioSettings)
    {
        this.ioSettings = ioSettings;
    }

    /**
     * Sets the memory settings for the new machine.
     *
     * @param memorySettings the memory settings
     */
    public void setMemorySettings(MemorySettings memorySettings)
    {
        this.memorySettings = memorySettings;
    }

    /**
     * Sets the networking settings for the new machine (for each network adapter).
     *
     * @param networksSettings the networking settings
     */
    public void setNetworksSettings(NetworkAdapterSettings[] networksSettings)
    {
        this.networksSettings = networksSettings;
    }

    /**
     * Sets the shared folder settings for the new machine.
     *
     * @param sharedFoldersSettings the shared folder settings
     */
    public void setSharedFoldersSettings(ArrayList<SharedFolderSettings> sharedFoldersSettings)
    {
        this.sharedFoldersSettings = sharedFoldersSettings;
    }

    /**
     * Sets the storage settings for the new machine.
     *
     * @param storageSettings the storage settings
     */
    public void setStorageSettings(StorageSettings storageSettings)
    {
        this.storageSettings = storageSettings;
    }

    /**
     * Sets the VRDP settings for the new machine.
     *
     * @param vrdpSettings the VRDP settings
     */
    public void setVrdpSettings(VRDPSettings vrdpSettings)
    {
        this.vrdpSettings = vrdpSettings;
    }

    /**
     * Sets the video settings for the new machine.
     *
     * @param videoSettings the video settings
     */
    public void setVideoSettings(VideoSettings videoSettings)
    {
        this.videoSettings = videoSettings;
    }

    /**
     * Checks if the networking settings are valid.
     *
     * @return <code>true</code> if the settings are valid or <code>false</code> otherwise
     */
    private boolean areNetworksSettingsValid()
    {
        if(networksSettings != null)
        {
            for(NetworkAdapterSettings adapterSettings : networksSettings)
            {
                if(adapterSettings != null && !adapterSettings.isValid())
                    return false;
                else
                    ;
            }
        }
        else
            ;

        return true;
    }

    /**
     * Checks if the shared folders settings are valid. <br><br>
     *
     * <b>Note:</b> <i>If the shared folder settings are set to <code>null</code>
     * they are still considered valid.</i>
     *
     * @return <code>true</code> if the settings are valid or <code>false</code> otherwise
     */
    private boolean areSharedFoldersSettingsValid()
    {
        if(sharedFoldersSettings != null)
        {
            for(SharedFolderSettings folderSettings : sharedFoldersSettings)
            {
                if(folderSettings != null && !folderSettings.isValid())
                    return false;
                else
                    ;
            }
        }
        else
            ;

        return true;
    }

    /**
     * Checks the validity of the request. <br><br>
     *
     * A request is considered valid only if all of the supplied data is valid.<br>
     * 
     * <b>Note:</b> <i>The required information for a valid machine creation request
     * is: permissions, machine name and OS type id. Any other settings can be left unset
     * (<code>null</code>).</i>
     *
     * @return <code>true</code> if the request is valid or <code>false</code> otherwise
     */
    @Override
    public boolean isValid()
    {
        if(super.isValid() && Functions.arePermissionsValid(permissions) && osTypeId != null
        /**/    && machineName != null && Functions.isLocationValid(machineName)
        /**/    && (audioSettings == null || audioSettings.isValid())
        /**/    && (biosSettings == null || biosSettings.isValid()
        /**/    && (bootSettings == null || bootSettings.isValid())
        /**/    && (cpuSettings == null || cpuSettings.isValid())
        /**/    && (ioSettings == null || ioSettings.isValid())
        /**/    && (memorySettings == null || memorySettings.isValid())
        /**/    && areNetworksSettingsValid()
        /**/    && areSharedFoldersSettingsValid()
        /**/    && (storageSettings == null || storageSettings.isValid())
        /**/    && (vrdpSettings == null || vrdpSettings.isValid())
        /**/    && (videoSettings == null || videoSettings.isValid())))
        {
            return true;
        }
        else
            return false;
    }

    /**
     * Returns a textual representation of the object. <br>
     *
     * It is in the form: "ClassName: (machineId,machineName,osTypeId,machineDescription,permissions)".
     *
     * @return the object represented as a String
     */
    @Override
    public String toString()
    {
        return CreateMachineRequest.class.getSimpleName()
                + ": (" + getMachineId() + "," + machineName + "," + osTypeId
                + "," + machineDescription + "," + permissions + ")";
    }
}
